package com.wishwall.persistence;

import java.util.UUID;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

import com.wishwall.exceptions.WishWallException;
import com.wishwall.persistence.managers.DeviceManager;
import com.wishwall.persistence.managers.UserManager;

/**
 *
 * @author yavor.gologanov
 *
 */
public class PersistenceContext {

	private static final String PERSISTENCE_UNIT_NAME = "WishWallServices";

	private static EntityManagerFactory entityManagerFactory = null;

	/**
	 * 
	 * @return
	 */
	public static PersistenceContext getPersistenceContext() {
		if (entityManagerFactory == null) {
			init();
		}
		return new PersistenceContext(entityManagerFactory.createEntityManager());
	}

	/**
	 * 
	 */
	public static void init() {
		entityManagerFactory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
	}

	/**
	 * 
	 * @return
	 */
	public static synchronized String createUUID() {
		UUID uid = UUID.randomUUID();
		return uid.toString().toUpperCase();
	}

	//---------------------------------------------------------------------------------------------

	private EntityManager entityManager = null;

	private DeviceManager deviceManager = null;
	private UserManager userManager = null;


	/**
	 *
	 * @param entityManager
	 */
	public PersistenceContext(EntityManager entityManager) {
		this.entityManager = entityManager;
	}

	/**
	 *
	 * @param action
	 * @return
	 * @throws WishWallException
	 */
	public <T> T run(TransactionalValueAction<T> action) throws WishWallException {
		try {

			entityManager.getTransaction().begin();
			T result = action.run();
			entityManager.getTransaction().commit();
			return result;

		} catch (Exception e) {
			entityManager.getTransaction().rollback();
			throw new WishWallException(e);
		}
	}

	/**
	 *
	 * @param action
	 * @throws WishWallException
	 */
	public void run(TransactionalAction action) throws WishWallException {
		try {

			entityManager.getTransaction().begin();
			action.run();
			entityManager.getTransaction().commit();

		} catch (Exception e) {

			if (entityManager.getTransaction().isActive()) {
				entityManager.getTransaction().rollback();
			}
			throw new WishWallException(e);
		}
	}

	/**
	 *
	 */
	public void close() {

		try {
			if (entityManager == null) {
				return;
			}

			if (entityManager.getTransaction().isActive()) {
				entityManager.getTransaction().rollback();
			}

			entityManager.close();
			entityManager = null;
		} catch (Exception e) {
			e.printStackTrace();
		}
	}


	/**
	 *
	 * @return
	 */
	public EntityManager getEntityManager() {
		return entityManager;
	}

	/**
	 *
	 * @return
	 */
	public DeviceManager getDeviceManager() {
		if (deviceManager == null) {
			deviceManager = new DeviceManager(this);
		}
		return deviceManager;
	}

	/**
	 * 
	 * @return
	 */
	public UserManager getUserManager() {
		if (userManager == null) {
			userManager = new UserManager(this);
		}
		return userManager;
	}

}
